package com.nancy.springioc.bean.factory.support;

import com.nancy.springioc.bean.factory.BeanDefinition;
import com.nancy.springioc.bean.factory.MutablePropertyValue;
import com.nancy.springioc.bean.factory.PropertyValue;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;

/**
 * 解释器，负责解析xml配置文件
 */
public class XmlBeanDefinitionReader implements BeanDefinitionReader {
    //声明一个BeanDefinitionRegistry类型的变量
    private BeanDefinitionRegistry registry;

    public XmlBeanDefinitionReader() {
        registry = new SimpleBeanDefinitionRegistry();
    }

    //获取注册表BeanDefinitionRegistry
    @Override
    public BeanDefinitionRegistry getRegistry() {
        return registry;
    }

    //加载资源配置文件，注册Bean数据,通过dom4j解析xml文件
    @Override
    public void loadBeanDefinitions(String location) throws Exception {
        //使用dom4j解析xml文件
        SAXReader reader = new SAXReader();

        //TODO InputStream resourceAsStream = XmlBeanDefinitionReader.class.getResourceAsStream(location);
        // 获取资源文件流，出现bug，无法获取到applicationContext.xml文件，原因未知
        /**
         * java.net.MalformedURLException: Cannot invoke "String.length()" because "spec" is null
         * 	at java.base/java.net.URL.<init>(URL.java:708)
         * 	at java.base/java.net.URL.<init>(URL.java:569)
         * 	at java.base/java.net.URL.<init>(URL.java:516)
         * 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:650)
         * 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:150)
         * 	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:861)
         * 	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:825)
         * 	at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
         * 	at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1224)
         * 	at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:637)
         * 	at org.dom4j.io.SAXReader.read(SAXReader.java:323)
         * 	at org.dom4j.io.SAXReader.read(SAXReader.java:246)
         * 	at com.nancy.springioc.bean.factory.support.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:39)
         * 	at com.nancy.springioc.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:25)
         * 	at com.nancy.springioc.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:22)
         * 	at com.nancy.springioc.business.controller.GoodsController.main(GoodsController.java:21)
         * Caused by: java.lang.NullPointerException: Cannot invoke "String.length()" because "spec" is null
         * 	at java.base/java.net.URL.<init>(URL.java:614)
         * 	... 15 more
         */
//        InputStream resourceAsStream = XmlBeanDefinitionReader.class.getResourceAsStream(location);

        InputStream resourceAsStream = XmlBeanDefinitionReader.class.getClassLoader().getResourceAsStream(location);
        Document document = reader.read(resourceAsStream);

        //从document中获取根元素
        Element rootElement = document.getRootElement();
        //获取根元素下Bean元素
        List<Element> beanElements = rootElement.elements("bean");
        //遍历bean元素
        for (Element beanElement : beanElements) {
            //解析bean元素，注册Bean数据
            String id = beanElement.attributeValue("id");
            String className = beanElement.attributeValue("class");

            //创建BeanDefinition对象
            BeanDefinition beanDefinition = new BeanDefinition(id, className);

            //创建MutablePropertyValue对象
            MutablePropertyValue mutablePropertyValue = new MutablePropertyValue();

            //获取bean元素下property元素
            List<Element> elementValueList = beanElement.elements("property");
            //遍历property元素
            for (Element element : elementValueList) {
                String name = element.attributeValue("name");
                String value = element.attributeValue("value");
                String ref = element.attributeValue("ref");

                //创建PropertyValue对象
                PropertyValue propertyValue = new PropertyValue(name, value, ref);
                mutablePropertyValue.addPropertyValue(propertyValue);
            }

            //设置MutablePropertyValue对象
            beanDefinition.setPropertyValue(mutablePropertyValue);

            //注册Bean数据
            registry.registerBeanDefinition(id, beanDefinition);
        }
    }
}
